/*
 * @Author: your name
 * @Date: 2020-05-06 11:07:13
 * @LastEditTime: 2020-08-04 12:56:36
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \truck\platform\main.c
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <execinfo.h> 

#include "xeLOG_internal.h"

#include "global_common.h"

#include "twtimer/aio-timeout.h"
#include "rbtree_queue.h"

rbtree_queue_t g_rb_queue_msg;

int _log_level = 7; // for internal
static void _hisome_sleep(int seconds);
// {
// 	STD_print("%d %d %d",sizeof(time_t),sizeof(long int),sizeof(long long));
//	for 64 bit 8 8 8
// 	exit(0);
// }
static int __sig_handle_calling=0;
#define BACKTRACE_NUM 30
void __my_sig_handle(int signum){
	
	xeLOG_ERR("get signal %d.",signum);
	STD_print("get signal %d.",signum);
	if(signum == 54)
		return;

	if(signum == SIGHUP)
		return;

	if(signum == SIGPIPE)
		return;

	if(signum == SIGTSTP)
		return;

	if(signum == SIGWINCH)
		return;

	if ( signum == SIGSEGV ) {
		char tracefile[128] = {0};
		void *trace[BACKTRACE_NUM];
		snprintf( tracefile, sizeof(tracefile)-1, "%s/alarm_strace", "./" );
		int n = backtrace(trace, BACKTRACE_NUM);
		int fd = open( tracefile, O_CREAT | O_WRONLY | O_APPEND, 0777 );
		if ( fd == -1 ) {
			backtrace_symbols_fd(trace, n, STDERR_FILENO);
		} else {
			char *cutoff = "---------------------\r\n";
			backtrace_symbols_fd(trace, n, fd);
			if ( write( fd, cutoff, strlen( cutoff )) > 0 )
				fdatasync( fd );
			close( fd );
		}
	}

	if ( __sig_handle_calling ) {
		return;
	}
	__sig_handle_calling = 1;
	

	if(signum!=499)
		sync();
	
	usleep(10000);

	exit(-1);
}

int signal_handle()
{
	int tuy;
	for( tuy = 1; tuy <=64; tuy++)
	{
		if ( tuy == SIGCHLD ) { continue; }
		if ( tuy == SIGCONT ) { continue; }
		if ( tuy == SIGALRM ) { continue; }
		if ( tuy == SIGTTIN ) { continue; }

		signal(tuy, __my_sig_handle);
	}
	return 0;
}

static int init_core_log(int tmp_log_level)
{
	int ret = 0;

#define logPath "/root/log"
#ifdef CONFIG_USE_EXTERNAL_XELOG
	init_xelog_local_t init = {0};
	if(access(logPath, F_OK) != 0){
		printf("%s is not exit, shoud be build \n", logPath);
		if(mkdir(logPath, 0755) == -1){   
		printf("mkdir %s error \n", logPath);   
		return -1;   
		}  
	}else{
		printf("%s is exit \n ", logPath);
	}
	init.local_port = 0;
	init.be_syslog  = 0;
	init.be_klog    = 0;
	init.log_level  = tmp_log_level;

	strcpy(init.path, logPath);

	init.num  = 20;
	init.size = 1*1024*1024;
	init.msg2stdout  = 0;
	if(tmp_log_level > 10)
		init.msg2stderr = 1;

	ret=init_xelog_local(&init);
	if(ret != 0) {
		xeLOG_ERR("init_xelog local fail.");
	}

	dprintf("init_xelog local success.\n");
#else
	_log_level = tmp_log_level;
#endif
	return ret;
}
static void _hisome_sleep(int seconds)
{
	struct timeval tv;
	gettimeofday(&tv,NULL);
	tv.tv_sec = seconds;
	tv.tv_usec = 0;
	select(0,NULL,NULL,NULL,&tv);
}
void *tw_proc_thread(void * arg)
{
  (void)arg;
  pthread_t id =pthread_self();
  if(pthread_detach(id) !=0){	
		pthread_exit(0);
  }
  STD_print("tw_proc_thread in");

  while(20201019){
      _hisome_sleep(2);
	//   STD_print("tw_proc_thread in");
      aio_timeout_process();
  }

}

deviceMgnt g_deviceList[5]={
	{0,"10.10.0.6"},
	{0,"10.10.0.8"},
	{0,"10.10.0.7"},

};

typedef void       (*msg_on_timeout)(char* param);

extern void g_general_mqtt_publish(char *topic,const char *message);


static void send1_timeout_endtime(void* param)
{
	deviceMgnt *p_devlist = (deviceMgnt *)(param);
    STD_print("send1_timeout_endtime p_devlist->ip:%s", p_devlist->ip);
    //_blockers_set_chanlist("all",0,BLOKCERS_ALL_OFF);
	
}

int tb_msg_release(tb_msg_t * p_msg)
{
	// p_msg->ref--;
	atomic_decrement32(&p_msg->ref);
	// STD_print("tb_msg_release:%d",p_msg->ref);
	if (0 != p_msg->ref)
		return 0;
	if(p_msg)
		free(p_msg);
}

int msg1_timeout(void* param)
{
	tb_msg_t *p_msg = (tb_msg_t *)param;

	//do private opt
	{
		deviceMgnt *p_devlist = (deviceMgnt *)(p_msg->priv_data);
		STD_print("msg1_timeout ip:%s\n",p_devlist->ip);
	}
	tb_msg_release(p_msg);

	RB_QUEUE_LOCK(&g_rb_queue_msg);
	rbtree_queue_erase(&g_rb_queue_msg,p_msg->msg_id);
	tb_msg_release(p_msg);
	RB_QUEUE_UNLOCK(&g_rb_queue_msg);

}

int msg_mqtt_send(char *topic,const char *payload,void *priv_data,msg_on_timeout ontimeout)
{
	cJSON * root = NULL;
	char *out = NULL;
	tb_msg_t * msg_send = NULL;
	char sid_str[128] = {0};

	root = cJSON_Parse(payload);
	if(!root){
		xeLOG_ERR("parse JSON failed,message:%s\n",payload);
		return -1;
	}

	msg_send = calloc(1,sizeof(tb_msg_t));
	if(!msg_send){
		xeLOG_ERR("parse JSON failed,message:%s\n",payload);
		goto send_exit;
	}
	msg_send->ref = 0;
	snprintf(sid_str, sizeof(sid_str)-1, "%p_%lld",
		&msg_send->timeout, system_clock());
	cJSON_AddStringToObject(root, "msg_id", sid_str);

	msg_send->priv_data = (void*)priv_data;
	strcpy(msg_send->msg_id, sid_str);

	out=cJSON_Print(root);
	g_general_mqtt_publish(topic,out);

	//add 1
	atomic_increment32(&msg_send->ref);
	// msg_send->ref++;
	aio_timeout_start(&msg_send->timeout,
		10000,
		ontimeout,(void *)msg_send);

	//add 1
	RB_QUEUE_LOCK(&g_rb_queue_msg);
	rbtree_queue_insert(&g_rb_queue_msg, sid_str, (void *)msg_send);
	//// msg_send->ref++;
	atomic_increment32(&msg_send->ref);
	RB_QUEUE_UNLOCK(&g_rb_queue_msg);

	STD_print("send:%s\n:%s\n",topic,out);
send_exit:
	if(out)
		free(out);
	cJSON_Delete(root);
}

int main(int argc, char **argv)
{
	int retval;
	int log_para = 5;

	xeLOG_NOTICE("mainstart...\n");
	signal_handle();

	hs_mqtt_init();
	sleep(2);
	{
		pthread_t threadID;
		if(pthread_create(&threadID,NULL, tw_proc_thread,NULL) != 0){
			STD_print("create tw_proc_thread fail!");
		}
	}
	rbtree_queue_init(&g_rb_queue_msg);

	{
		deviceMgnt *p_devlist;
		p_devlist = &g_deviceList[0];
		#define TEST_TOPIC "OPT"
		char payload_str[HISOME_LEN_256]={0};
		snprintf(payload_str, sizeof(payload_str)-1,
			"{\"iterm\":\"devlist\",\"ip\":\"all\"}");
	
		msg_mqtt_send(TEST_TOPIC,payload_str,(void *)p_devlist,msg1_timeout);

	}
	sleep(50);
		// pause();

	return 0;
}

//  int get_free_memory ( )
//  {
// 	 static FILE* fd = NULL;
// 	 static int memfree = 0;
// 	 static char buff[128] = {0};
// 	 static char memstr[64] = {0};
// 	 static char unit[32] = {0};
 
// 	 fd = fopen("/proc/meminfo", "r" );
// 	 if ( fd == NULL ) {
// 		 return -1;
// 	 }
 
// 	 do{
// 		 if (fgets (buff, sizeof(buff), fd) == NULL )
// 			 break;
// 		 if (sscanf (buff, "%s %d %s", memstr, &memfree, unit) != 3 )
// 			 continue;
// 		 if (strcmp( memstr, "MemFree:" ) == 0 ) {
// 			 fclose(fd); 
// 			 return memfree;
// 		 }
// 	 } while(20200727);
 
// 	 fclose(fd); 
// 	 return -1;
//  }

// extern in_addr_t z_gethostbyname(const char *name);
// int my_test(char *remote_ip)
// {
// 		struct in_addr sin_addr;
// 		memset(&sin_addr,0,sizeof(sin_addr));
// 		sin_addr.s_addr=z_gethostbyname(remote_ip);
// 		printf("tinybear %s\n",inet_ntoa(sin_addr));	
// }
// const char *
// Inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
// {
// 	const char	*ptr;

// 	if (strptr == NULL)		/* check for old code */
// 		printf("NULL 3rd argument to inet_ntop");
// 	if ( (ptr = inet_ntop(family, addrptr, strptr, len)) == NULL)
// 		printf("inet_ntop error");		/* sets errno */
// 	return(ptr);
// }
// int my_test2(char *ptr)
// {
// 	char **pptr;
// 	char	str[128];
// 	struct hostent	*hptr;
// 	{
// 		printf("ptr:%s\n",ptr);
// 		if ( (hptr = gethostbyname(ptr)) == NULL) {
// 			printf("gethostbyname error for host: %s: %s",
// 					ptr, hstrerror(h_errno));
// 			return 0;
// 		}
// 		printf("official hostname: %s %d\n", hptr->h_name,hptr->h_length);

// 		for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
// 			printf("\talias: %s\n", *pptr);

// 		switch (hptr->h_addrtype) {
// 		case AF_INET:
// 			pptr = hptr->h_addr_list;
// 			for ( ; *pptr != NULL; pptr++)
// 				printf("\taddress: %s\n",
// 					Inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
// 			break;

// 		default:
// 			printf("unknown address type");
// 			break;
// 		}
// 	}
// }

// #define SOCKET_ADDRLEN 32
// static inline int socket_ipv4( const char* ipv4_or_dns,  char ip[SOCKET_ADDRLEN])
// {
// 	int r;
// 	struct addrinfo hints, *addr;
// 	memset(&hints, 0, sizeof(hints));
// 	hints.ai_family = AF_INET;
// //	hints.ai_flags = AI_ADDRCONFIG;
// 	r = getaddrinfo(ipv4_or_dns, NULL, &hints, &addr);
// 	if (0 != r)
// 		return r;

// 	assert(AF_INET == addr->ai_family);
// 	inet_ntop(AF_INET, &(((struct sockaddr_in*)addr->ai_addr)->sin_addr), ip, SOCKET_ADDRLEN);
// 	freeaddrinfo(addr);
// 	return 0;
// }
// int my_test3(char *ptr)
// {
// 	char ip_str[32];
// 	int ret = -1;
// 	ret = socket_ipv4(ptr,ip_str);
// 	if(ret){
// 		printf("get error\n");
// 	}else{
// 		printf("ip_str:%s\n",ip_str);
// 	}
// }
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  main
 *  Description:  2020-3-25 15:51:18
 * =====================================================================================
 */